﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SdnfValidator
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.MaximizeBox = false;

            // 如果程序目录有Tekla.map 则自动加载该文件
            var mapFilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Tekla.map");
            if (File.Exists(mapFilePath))
            {
                this.textBox1.Text = mapFilePath;
                if (!MapFileValidate(mapFilePath))
                {
                    this.textBox1.Text = "";
                    this.textBox1.ResetBackColor();
                }                
            }            
        }

        // 全局哈希表，用于储存map字典
        Hashtable hashtable = new Hashtable();

        // 拖入map文件
        private void textBox1_DragDrop(object sender, DragEventArgs e)
        {
            string[] fileNames = (string[])e.Data.GetData(DataFormats.FileDrop, false);

            if (fileNames.Length == 1)
            {
                this.textBox1.Text = fileNames[0];
                MapFileValidate(fileNames[0]);
            }
        }

        // 校验map文件
        private bool MapFileValidate(string fname)
        {
            this.label3.Text = "";
            if (this.textBox1.Text == "" || !isFile(fname))
            {
                this.textBox1.BackColor = Color.Red;
                this.label3.Text = "请拖入Map文件!";
                return false;
            }

            // 检查被拖入的文件第一行是否是 PDMS TEKLA
            string firstLine = "";
            string lines = "";
            try
            {
                using (StreamReader sr = new StreamReader(fname))
                {
                    firstLine = sr.ReadLine();
                    lines = sr.ReadToEnd();
                }
            }
            catch (IOException e)
            {
                this.label3.Text = "The file could not be read:";
                this.label3.Text += e.Message;
                return false;
            }

            bool isMatch = Regex.IsMatch(firstLine, @"pdms\s+tekla", RegexOptions.IgnoreCase);
            if (!isMatch)
            {
                this.textBox1.BackColor = Color.Red;
                this.label3.Text = "Map文件不正确!";
                return false;
            }

            // 检查 Map 文件是否有错误 
            // 正确的格式应该是 PDMS截面空格+ TEKLA截面 空格+

            string[] ArrayLines = Regex.Split(lines.Trim(), @"\s+");
            if (ArrayLines.Length % 2 != 0)
            {
                this.textBox1.BackColor = Color.Red;
                this.label3.Text = "Map文件格式错误! PDMS和TEKLA截面不是一一对应。";
                return false;
            }
            hashtable.Clear();
            for (int i = 0; i < ArrayLines.Length; i++)
            {
                if (i % 2 == 1)
                {
                    var k = ArrayLines[i];
                    if (!hashtable.ContainsKey(k))
                    {
                        hashtable.Add(k, "");
                    }

                }
            }

            this.textBox1.ResetBackColor();
            return true;
        }

        // 校验SDNF文件
        private bool SdnfFileValidate(string fname)
        {
            var lines = "";

            // 检查是否可读
            try
            {
                using (StreamReader sr = new StreamReader(fname))
                {
                    lines = sr.ReadToEnd();
                }
            }
            catch (IOException e)
            {
                this.richTextBox1.Text += fname;
                this.richTextBox1.Text += " could not be read:";
                this.richTextBox1.Text += e.Message;
                this.richTextBox1.Text += "\n";
                return false;
            }

            // 检查是否是SDNF 3.0
            bool isMatch = Regex.IsMatch(lines, @"SDNF\s+Version\s3.0", RegexOptions.IgnoreCase);
            if (!isMatch)
            {
                this.richTextBox1.Text += fname;
                this.richTextBox1.Text += " is not a SDNF 3.0 File!";
                this.richTextBox1.Text += "\n";
                return false;
            }

            // 检查截面是否存在

            lines = Regex.Replace(lines, @"(?<=\r\n)#.*\r\n", "");
            lines = Regex.Replace(lines, @"^#.*\r\n", "");
            lines = lines.Trim() + "\r\nPacket";

            // 必须指明 RegexOptions.Singleline 
            // 否则 .* 不匹配 \r\n
            var Beams = Regex.Matches(lines, @"(?<=\r\n)Packet\s+10.*?(?=\r\nPacket)", RegexOptions.Singleline);

            // 未找到 Packet 10 是可能的
            if (Beams.Count == 0)
            {
                //this.richTextBox1.Text += fname;
                //this.richTextBox1.Text += " does not have Beams !";
                //this.richTextBox1.Text += "\n";
                return true;
            }

            // 如果Packet 10 出现多次 说明数据有问题
            if (Beams.Count > 1)
            {
                this.richTextBox1.Text += fname;
                this.richTextBox1.Text += " has too many Packet 10 !";
                this.richTextBox1.Text += "\n";
                return false;
            }

            // 如果Packet 10 有一个包 应该是 10*n + 2 行数据
            var Beam = Beams[0].ToString();
            var BeamArray = Regex.Split(Beam, @"[\r\n]+");

            if ((BeamArray.Length % 10) != 2)
            {
                this.richTextBox1.Text += fname;
                this.richTextBox1.Text += " has something wrong in Packet 10 !";
                this.richTextBox1.Text += "\n";
                return false;
            }

            bool flag = true;
            for (int i = 0; i < BeamArray.Length / 10; i++)
            {
                // 截面信息在去除头两行 后数据中第二行
                var SectionArray = Regex.Split(BeamArray[i * 10 + 3].Trim(),@"\s+");
                if (SectionArray.Length != 5)
                {
                    flag = false;
                    this.richTextBox1.Text += fname;
                    this.richTextBox1.Text += " has wrong section ";
                    this.richTextBox1.Text += BeamArray[i * 10 + 3];
                    this.richTextBox1.Text += "\n";
                }
                else
                {
                    var section = SectionArray[0].Replace("\"","").Trim();
                    if (!hashtable.ContainsKey(section))
                    {
                        // 需要排除自定义截面
                        // 自定义截面规则 
                        // HI\d+-\d+-\d+\*\d+|PL\d+\*\d+|D\d+|CC\d+-\d+-\d+-\d+|ZZ\d+-\d+-\d+-\d+|Z\d+\*\d+\*\d+
                        if (!Regex.IsMatch(section, @"HI\d+-\d+-\d+\*\d+|PL\d+\*\d+|D\d+|CC\d+-\d+-\d+-\d+|ZZ\d+-\d+-\d+-\d+|Z\d+\*\d+\*\d+"))
                        {
                            flag = false;
                            this.richTextBox1.Text += fname;
                            this.richTextBox1.Text += " section not in map: ";
                            this.richTextBox1.Text += section;
                            this.richTextBox1.Text += "\n";
                        }
                    }
                }                
            }
            return flag;

        }

        private bool isFile(string fname)
        {
            FileAttributes attr = File.GetAttributes(fname);
            if (attr.HasFlag(FileAttributes.Directory))
                return false;
            else
                return true;
        }

        private bool isDir(string fname)
        {
            FileAttributes attr = File.GetAttributes(fname);
            if (attr.HasFlag(FileAttributes.Directory))
                return true;
            else
                return false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // 检查map文件
            string fname = this.textBox1.Text;
            if (!MapFileValidate(fname))
            {
                return;
            }

            // 检查 SDNF 文件
            for (int i = 0; i < this.dataGridView1.Rows.Count; i++)
            {
                DataGridViewRow row = dataGridView1.Rows[i];
                var fp = row.Cells[3].Value.ToString();

                if (!SdnfFileValidate(fp))
                {
                    // row.Cells[0].Style.BackColor = Color.Red;
                    row.DefaultCellStyle.BackColor = Color.Red;
                    row.Cells[2].Value = "error";
                }
                else
                {
                    row.Cells[2].Value = "ok";
                }
            }

            MessageBox.Show("检查完成!");

        }

        private void dataGridView1_DragDrop(object sender, DragEventArgs e)
        {
            string[] fileNames = (string[])e.Data.GetData(DataFormats.FileDrop, false);

            if (fileNames.Length > 0)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("文件名", typeof(string));
                dt.Columns.Add("文件类型", typeof(string));
                dt.Columns.Add("检查状态", typeof(string));
                dt.Columns.Add("文件路径", typeof(string));

                foreach (var file in fileNames)
                {
                    if (isDir(file))
                    {
                        string[] allfiles = System.IO.Directory.GetFiles(file, "*.*", System.IO.SearchOption.AllDirectories);
                        foreach (var f in allfiles)
                        {
                            DataRow row = dt.NewRow();
                            var name = Path.GetFileNameWithoutExtension(f);
                            var ext = Path.GetExtension(f);
                            var status = "未检查";
                            row["文件名"] = name;
                            row["文件类型"] = ext;
                            row["检查状态"] = status;
                            row["文件路径"] = f;
                            dt.Rows.Add(row);
                        }
                    }
                    else
                    {
                        DataRow row = dt.NewRow();
                        var name = Path.GetFileNameWithoutExtension(file);
                        var ext = Path.GetExtension(file);
                        var status = "未检查";
                        row["文件名"] = name;
                        row["文件类型"] = ext;
                        row["检查状态"] = status;
                        row["文件路径"] = file;
                        dt.Rows.Add(row);
                    }
                }
                this.dataGridView1.DataSource = dt;
                this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;

            }
        }
        private void dataGridView1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Copy;
            else
                e.Effect = DragDropEffects.None;
        }
        private void textBox1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Copy;
            else
                e.Effect = DragDropEffects.None;
        }


    }
}
